#include <linux/tty.h>
#include <asm/io.h>
#include <asm/system.h>
#include <mystdio.h>
#include<mystdio.h>
#include<string.h>
	
#define ORIG_X          (*(unsigned char *)0x90000)
#define ORIG_Y          (*(unsigned char *)0x90001)
#define ORIG_VIDEO_PAGE     (*(unsigned short *)0x90004)
#define ORIG_VIDEO_MODE     ((*(unsigned short *)0x90006) & 0xff)
#define ORIG_VIDEO_COLS     (((*(unsigned short *)0x90006) & 0xff00) >> 8)
#define ORIG_VIDEO_LINES    ((*(unsigned short *)0x9000e) & 0xff)
#define ORIG_VIDEO_EGA_AX   (*(unsigned short *)0x90008)
#define ORIG_VIDEO_EGA_BX   (*(unsigned short *)0x9000a)
#define ORIG_VIDEO_EGA_CX   (*(unsigned short *)0x9000c)

#define VMODE (*(unsigned short *)0x90010)
#define SCRNX (*(unsigned short *)0x90012)
#define SCRNY (*(unsigned short *)0x90014)
//#define VIDEO_MEM_BASE (*(unsigned int *)0x90016)

#define VIDEO_TYPE_MDA      0x10    /* Monochrome Text Display  */
#define VIDEO_TYPE_CGA      0x11    /* CGA Display          */
#define VIDEO_TYPE_EGAM     0x20    /* EGA/VGA in Monochrome Mode   */
#define VIDEO_TYPE_EGAC     0x21    /* EGA/VGA in Color Mode    */
	
static unsigned char    video_type;     /* Type of display being used   */
static unsigned long    video_num_columns;  /* Number of text columns   */
static unsigned long    video_num_lines;    /* Number of test lines     */
static unsigned long    video_mem_base;     /* Base of video memory     */
static unsigned long    video_mem_term;     /* End of video memory      */
static unsigned long    video_size_row;     /* Bytes per row        */
static unsigned char    video_page;     /* Initial video page       */
static unsigned short   video_port_reg;     /* Video register select port   */
static unsigned short   video_port_val;     /* Video register value port    */
static unsigned short   video_erase_char;

static unsigned long    origin;
static unsigned long    scr_end;
static unsigned long    pos;
static unsigned long    x, y;
static unsigned long    fontx, fonty;
static unsigned long    top, bottom;
static unsigned long    attr = 0x07;
static unsigned long    BCK = DARKYELLOW;
	
static char buf[8];
	
	
static inline void gotoxy(int new_x,unsigned int new_y) {
    if (new_x > video_num_columns || new_y >= video_num_lines)
        return;
	
    x = new_x;
    y = new_y;
    pos = origin + y*video_size_row + x; //(x << 1);
}
	
static inline void set_cursor() {
    cli();
    outb_p(14, video_port_reg);
    outb_p(0xff&((pos-video_mem_base)>>9), video_port_val);
    outb_p(15, video_port_reg);
    outb_p(0xff&((pos-video_mem_base)>>1), video_port_val);
    sti();
}
		

void con_init() {
    fontx=8;
    fonty=16;
    video_num_columns = SCRNX/fontx; //1024/8;
    video_size_row = video_num_columns;
    video_num_lines = SCRNY/fonty; //1024/8;
    video_page = 1;
    video_erase_char=0x0720;
	
    origin = 0;
    pos=0;
    scr_end = origin + video_num_lines * video_size_row;
    top = 0;
    bottom  = video_num_lines;
	
    x=0;
    y=0;
    gotoxy(ORIG_X, ORIG_Y);
    //set_cursor();
    console_print("hello\r\n");
}

static void scrup() {
    if (!top && bottom == video_num_lines) {
        origin += video_size_row;
        pos += video_size_row;
        scr_end += video_size_row;

        if (scr_end > video_mem_term) {
            __asm__("cld\n\t"
                    "rep\n\t"
                    "movsl\n\t"
                    "movl video_num_columns,%1\n\t"
                    "rep\n\t"
                    "stosw"
                    ::"a" (video_erase_char),
                    "c" ((video_num_lines-1)*video_num_columns>>1),
                    "D" (video_mem_base),
                    "S" (origin):);
            scr_end -= origin-video_mem_base;
            pos -= origin-video_mem_base;
            origin = video_mem_base;
        }
        else {
             __asm__("cld\n\t"
                     "rep\n\t"
                     "stosw"
                     ::"a" (video_erase_char),
                     "c" (video_num_columns),
                     "D" (scr_end-video_size_row):);
        }
        //set_origin();
    }
    else {
        __asm__("cld\n\t"
                "rep\n\t"
                "movsl\n\t"
                "movl video_num_columns,%%ecx\n\t"
                "rep\n\t"
                "stosw"
                ::"a" (video_erase_char),
                "c" ((bottom-top-1)*video_num_columns>>1),
                "D" (origin+video_size_row*top),
                "S" (origin+video_size_row*(top+1)):);
    }
}

static void lf() {
    if (y + 1 < bottom) {
        y++;
        pos += video_size_row;
        return;
    }
    //scrup();
}

static void cr() {
    pos -= x << 1;
    x = 0;
}

static void del() {
    if (x) {
        pos -= 2;
        x--;
        *(unsigned short*)pos = video_erase_char;
    }
}
	
void console_print000(unsigned char * vram, int xsize, int ysize, const char* buf) {
    char* t = (char*)pos;
    char* s = buf;
    int i = 0;
    int nr=strlen(buf);	
    for (i=0; i<nr; i++) {
        //*t++ = *(s++);
        //putfont8(0, SCRNX, x*8, y*8, BLACK, *(s++));
        //*t++ = 0xf;
       //while(nr--) {
        char c = *s++;
        if (c=='\0')return;
        if (c > 31 && c < 127) {
            if (x >= video_num_columns) {
                x -= video_num_columns;
                pos -= video_size_row;
                lf();
            }

            putfont8bck(vram, xsize, ysize, x*fontx, y*fonty, (x+1)*fontx-1, 
             (y+1)*fonty-1, attr, BCK, c);
            //boxfill8(0, SCRNX, SCRNY, BCK, x*fontx, y*fonty, x*fontx+8, y*fonty+16);
            //putfont8(0, SCRNX, x*fontx, y*fonty, attr, c);
            //*(char *)pos = c;
            //*(((char*)pos) + 1) = attr;
            pos += 1;
            x++;
        }
        else if (c == 10 || c == 11 || c == 12)
            lf();
        else if (c == 13)
            cr();
        else if (c == 127) {
            del();
        }
        else if (c == 8) {
            if (x) {
                x--;
                pos -= 1; //2;
            }
        }
    }
	
    pos = (long)t;
    gotoxy(x, y);
    set_cursor();
}

void console_print0(unsigned char* vram, int xsize, int ysize, const char* buf) {
    char* t = (char*)pos;
    char* s = buf;
    int i = 0;
    int nr=strlen(buf);
        
    for (i = 0; i < nr; i++) {
        //*t++ = *(s++);
        //putfont8(0, SCRNX, x*8, y*8, BLACK, *(s++));
        //*t++ = 0xf;
       //while(nr--) {
        char c = *s++;
        if (c > 31 && c < 127) {
            if (x >= video_num_columns) {
                x -= video_num_columns;
                pos -= video_size_row;
                lf();
            }

            //boxfill8(0, xsize, ysize, BCK, x*fontx, y*fonty, (x+1)*fontx, (y+1)*fonty);
            //putfont8(0, xsize, x*fontx, y*fonty, attr, c);
            putfont8bck(vram, xsize, ysize, x*fontx, y*fonty, (x+1)*fontx-1, (y+1)*fonty-1, attr, BCK, c);
            //*(char *)pos = c;
            //*(((char*)pos) + 1) = attr;
            pos += 1;
            x++;
        }
        else if (c == 10 || c == 11 || c == 12)
            lf();
        else if (c == 13)
            cr();
        else if (c == 127) {
            del();
        }
        else if (c == 8) {
            if (x) {
                x--;
                pos -= 2;
            }
        }
    //}

    pos = (long)t;
    //gotoxy(x, y);
    //set_cursor();
}
}

void console_print00(unsigned char * vram, int xsize, int ysize, int x0, int y0, unsigned char color, const char* buf){
   int x00=x, y00=y, pos00=pos;
   unsigned char attr00=attr;
   attr=color;
   gotoxy(x0,y0);
   console_print0(vram, xsize, ysize, buf);
   gotoxy(x00,y00);
   attr=attr00;
}

void console_print(const char* buf) {
    console_print0(0, SCRNX, SCRNY, buf);
}

